home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
stdio
/
c
/
scan
< prev
next >
Wrap
Text File
|
1996-11-09
|
14KB
|
871 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/stdio/c/RCS/scan,v $
* $Date: 1996/04/19 21:32:42 $
* $Revision: 1.1 $
* $State: Rel $
* $Author: simon $
*
* $Log: scan,v $
* Revision 1.1 1996/04/19 21:32:42 simon
* Initial revision
*
***************************************************************************/
static const char rcs_id[] = "$Id: scan,v 1.1 1996/04/19 21:32:42 simon Rel $";
/* Implements __scanf(fp,format,argp,cnt) which is called by all
* scanf() functions to perform formatted input. __scanf() returns a count
* of the number of characters read. *cnt is assigned to an item count. */
/* A conversion is of the form "%[*][width][size]function".
* For full details RTFM for scanf(3). */
#include <sys/syslib.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#define IGNORE(x) x = x
__STDIOLIB__
#define ungetc(c,f) \
(((f)->i_ptr > (f)->i_base) ? ((f)->i_cnt++,*--(f)->i_ptr = (c)) : -1)
/* To avoid truncation SCBUFSIZ should be 256+.
* This library will *not* buffer overflow unless SCBUFSIZ < 4. */
#define SCBUFSIZ 256 /* size of buffer for %feEgG & %[ */
/* the prototypes for the input functions */
static int __s_nin (FILE *, va_list *, const char **);
static int __s_char (FILE *, va_list *, const char **);
static int __s_str (FILE *, va_list *, const char **);
static int __s_sdec (FILE *, va_list *, const char **);
static int __s_sint (FILE *, va_list *, const char **);
static int __s_uoct (FILE *, va_list *, const char **);
static int __s_udec (FILE *, va_list *, const char **);
static int __s_uhex (FILE *, va_list *, const char **);
static int __s_fdbl (FILE *, va_list *, const char **);
static int __s_ptr (FILE *, va_list *, const char **);
static int __s_sdel (FILE *, va_list *, const char **);
/* __scnt is set to the number of characters read by __scanf() and
* is used by __s_nin() to output the number of characters read. */
static size_t __scnt;
static int __scflag; /* assignment suppression flag */
static int __scsize; /* -1 = unspecified */
static unsigned int __scwidth; /* width */
static signed char __scfnc[32] = /* conversions */
{
-1, -1,
1, /* %c */
3, /* %d */
8, /* %eE */
8, /* %f */
8, /* %gG */
-1,
4, /* %i */
-1, -1, -1, -1,
0, /* %n */
5, /* %o */
9, /* %p */
-1, -1,
2, /* %s */
-1,
6, /* %u */
-1, -1,
7, /* %xX */
-1, -1, -1, -1, -1, -1, -1, -1
};
/* __scfn[] is the array of input functions called by __scanf() -
* They return a value indicating whether they successfully interpreted
* the input or not. 0 indicates failure; a +ve value is a count
* of the number of characters read. */
static int (*__scfn[]) (FILE *, va_list *, const char **) =
{
__s_nin, /* %n no. of characters read so far */
__s_char, /* %c character */
__s_str, /* %s string */
__s_sdec, /* %d signed decimal */
__s_sint, /* %i signed integer */
__s_uoct, /* %o unsigned octal */
__s_udec, /* %u unsigned decimal */
__s_uhex, /* %xX unsigned hex */
__s_fdbl, /* %feEgG float (double) */
__s_ptr, /* %p unsigned hex value of pointer */
__s_sdel /* %[ delimited string */
};
/* __scanf() */
int
__scanf (register FILE * f, const char *format, va_list ap, int *cnt)
{
register const char *s1 = format;
register int n = 0;
register int c;
for (;;)
{
if (!(c = *s1++))
goto ret;
if (isspace (c))
continue; /* white space in formatting string is ignored */
if (c != '%')
{
register int m, l = 0;
match:
do
{
if ((l++, m = getc (f)) < 0)
{
if (!n)
goto eof;
goto ret;
}
}
while (isspace (m));
__scnt += l;
if (m == c)
continue;
(void) ungetc (m, f);
goto ret;
}
else
{
if (!(c = *s1++))
goto ret;
if (c == '%')
goto match;
}
{ /* we now have a % conversion */
register int i, j;
const char *s;
/* looking for "%[*][width][size]function" */
/* set __scflag */
__scflag = 0;
if (c == '*')
{
if (!(c = *s1++))
goto ret;
__scflag = 1;
}
/* set __scwidth */
__scwidth = 0;
if (isdigit (c))
{
__scwidth = (unsigned int) strtoul (s1 - 1, (char **) &s, 0);
s1 = s;
if (!(c = *s1++))
goto ret;
if (__scwidth > SCBUFSIZ)
__scwidth = SCBUFSIZ;
}
/* set __scsize */
switch (c)
{
case 'h':
__scsize = 0;
if (!(c = *s1++))
goto ret;
break;
case 'l':
__scsize = 1;
if (!(c = *s1++))
goto ret;
break;
case 'L':
__scsize = 2;
if (!(c = *s1++))
goto ret;
break;
default:
__scsize = -1;
break;
}
/* call appropriate input function */
i = (c == '[') ? 10 : __scfnc[(_tolower (c) - 'a') & 31];
if (i >= 0)
{
s = s1;
j = __funcall ((*__scfn[i]), (f, (va_list *) (&ap), &s));
s1 = s;
if (j < 0 && !n)
goto eof;
else if (j <= 0)
goto ret;
else
{
__scnt += j;
if (!__scflag)
n++;
}
}
else
{
if (!n)
goto eof;
goto ret;
}
}
}
ret:*cnt = n;
return (__scnt);
eof:*cnt = 0;
return (-1);
}
/* __s_nin() */
static int
__s_nin (register FILE * f, va_list * ap, const char **e)
{
IGNORE (e);
IGNORE (f);
if (!__scflag)
{
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) __scnt;
break;
case 1:
*va_arg (*ap, long *) = (long) __scnt;
break;
default:
*va_arg (*ap, int *) = (int) __scnt;
break;
}
}
return (0);
}
/* __s_char() */
static int
__s_char (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register char *s;
register int c;
IGNORE (e);
w = __scwidth;
if (!w)
w = 1; /* default - 1 char */
s = __scflag ? 0 : va_arg (*ap, char *);
while (w)
{
if ((c = getc (f)) < 0)
return (n ? n : -1);
if (s)
*s++ = c;
n++, w--;
}
return (n);
}
/* __s_str() */
static int
__s_str (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register char *s;
register int c;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
s = __scflag ? 0 : va_arg (*ap, char *);
do
{
if ((c = getc (f)) < 0)
{
if (s)
*s = 0;
return (-1);
}
}
while (isspace (c));
while (!isspace (c) && w)
{
if (s)
*s++ = c;
n++, w--;
if ((c = getc (f)) < 0)
{
if (s)
*s = 0;
return (n);
}
}
if (s)
*s = 0;
(void) ungetc (c, f);
return (n);
}
/* __s_sdec() */
static int
__s_sdec (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register int i = 0, i_ = 0;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
if (c == '+' || c == '-')
{
if (c == '-')
i_ = 1;
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
while (isdigit (c) && w)
{
i = i * 10 + (c - '0');
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
(void) ungetc (c, f);
ret:if (!__scflag && n)
{
if (i_)
i = -i;
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) i;
break;
case 1:
*va_arg (*ap, long *) = (long) i;
break;
default:
*va_arg (*ap, int *) = i;
break;
}
}
return (n);
}
/* __s_sint() */
static int
__s_sint (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register int i = 0, i_ = 0;
register int b = 10;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
if (c == '+' || c == '-')
{
if (c == '-')
i_ = 1;
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
if (c == '0' && w)
{
b = 010;
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
if ((c == 'x' || c == 'X') && w)
{
b = 0x10;
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
}
switch (b)
{
case 010:
while (c >= '0' && c < '8' && w)
{
i = i * b + (c - '0');
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
break;
case 10:
while (isdigit (c) && w)
{
i = i * b + (c - '0');
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
break;
case 0x10:
while (isxdigit (c) && w)
{
i = i * b + ((c > '9') ? ((c & 31) + 9) : (c - '0'));
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
break;
}
(void) ungetc (c, f);
ret:if (!__scflag && n)
{
if (i_)
i = -i;
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) i;
break;
case 1:
*va_arg (*ap, long *) = (long) i;
break;
default:
*va_arg (*ap, int *) = i;
break;
}
}
return (n);
}
/* __s_uoct() */
static int
__s_uoct (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register unsigned int i = 0;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
while (c >= '0' && c <= '7' && w)
{
i = i * 010 + (c - '0');
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
(void) ungetc (c, f);
ret:if (!__scflag && n)
{
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) i;
break;
case 1:
*va_arg (*ap, long *) = (long) i;
break;
default:
*va_arg (*ap, int *) = i;
break;
}
}
return (n);
}
/* __s_udec() */
static int
__s_udec (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register unsigned int i = 0;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
while (isdigit (c) && w)
{
i = i * 10 + (c - '0');
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
(void) ungetc (c, f);
ret:if (!__scflag && n)
{
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) i;
break;
case 1:
*va_arg (*ap, long *) = (long) i;
break;
default:
*va_arg (*ap, int *) = i;
break;
}
}
return (n);
}
/* __s_uhex() */
static int
__s_uhex (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register unsigned int i = 0;
IGNORE (e);
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
if (c == '0' && w)
{
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
if ((c == 'x' || c == 'X') && w)
{
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
}
while (isxdigit (c) && w)
{
i = i * 0x10 + (isdigit (c) ? (c - '0') : ((c & 7) + 9));
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
}
(void) ungetc (c, f);
ret:if (!__scflag && n)
{
switch (__scsize)
{
case 0:
*va_arg (*ap, short *) = (short) i;
break;
case 1:
*va_arg (*ap, long *) = (long) i;
break;
default:
*va_arg (*ap, int *) = i;
break;
}
}
return (n);
}
/* __s_fdbl() */
static int
__s_fdbl (register FILE * f, va_list * ap, const char **e)
{
register unsigned int w;
register int n = 0;
register int c;
register double i;
register char *s;
register int l = 0;
#define F_SIGN 0001
#define F_DP 0002
#define F_XP 0004
#define F_XSIGN 0010
IGNORE (e);
if (!__scflag)
{
if (!(s = __sbuf))
if (!(s = __sbuf = malloc (SCBUFSIZ)))
return (0);
}
else
s = 0;
w = __scwidth;
if (!w)
w = SCBUFSIZ;
do
{
if ((c = getc (f)) < 0)
return (-1);
}
while (isspace (c));
if ((c == '-' || c == '+') && !(l & F_SIGN))
{
l |= F_SIGN;
goto l1;
}
if (!isdigit (c))
goto l2;
l1:
if (!w)
goto ret;
if (s)
*s++ = c;
n++, w--;
if ((c = getc (f)) < 0)
goto ret;
if (isdigit (c))
goto l1;
l2:
if ((c == '-' || c == '+') && (l & F_XP) && !(l & F_XSIGN))
{
l |= F_XSIGN;
goto l1;
}
if (c == '.' && !(l & F_DP))
{
l |= F_DP;
goto l1;
}
if ((c == 'e' || c == 'E') && !(l & F_XP))
{
l |= F_XP;
goto l1;
}
ret:if (c >= 0)
(void) ungetc (c, f);
if (!__scflag && n)
{
*s = 0;
i = strtod (__sbuf, 0);
switch (__scsize)
{
case 2:
*va_arg (*ap, long double *) = (long double) i;
break;
case 1:
*va_arg (*ap, double *) = i;
break;
default:
*va_arg (*ap, float *) = (float) i;
break;
}
}
return (n);
#undef F_SIGN
#undef F_DP
#undef F_XP
#undef F_XSIGN
}
/* __s_ptr() */
static int
__s_ptr (register FILE * f, va_list * ap, const char **e)
{
return (__s_uhex (f, ap, e));
}
/* __s_sdel() */
static int
__s_sdel (register FILE * f, va_list * ap, const char **e)
{
register const char *o;
register char *s, *d;
register int w, n = 0, m = 0, c;
if (!(d = __sbuf))
if (!(d = __sbuf = malloc (SCBUFSIZ)))
return (0);
o = (*e);
if (*o == '^')
o++, m++;
w = SCBUFSIZ;
if (*o == ']')
*d++ = *o++, w--;
while (w--)
{
if (!(c = *o++) || c == ']')
break;
*d++ = c;
}
(*e) = o;
*d = 0;
d = __sbuf;
w = __scwidth;
if (!w)
w = SCBUFSIZ;
s = __scflag ? 0 : va_arg (*ap, char *);
if ((c = getc (f)) < 0)
{
if (s)
*s = 0;
return (-1);
}
while (w--)
{
if (!strchr (d, c) ^ m)
break;
if (s)
*s++ = c;
n++;
if ((c = getc (f)) < 0)
goto ret;
}
(void) ungetc (c, f);
ret:if (s)
*s = 0;
return (n);
}